#pragma once

#include "Light.h"
#include "Camera.h"


namespace rt
{
	struct Sphere;
	struct Plane;
	struct Box;
	struct Blob;
	struct Material;
	struct Algeb;

	class Scene
	{
	public:
		OVERRIDE_NEW_DELETE_WITH_ALIGNMENT(16);

		Scene();
		virtual ~Scene();

		typedef std::vector<Light *> LightList;

		const LightList & GetLights() const { return mLights; }
		Light * CreateLight();

		Material * CreateMaterial();

		float GetFieldOfViewInRadians() const { return mFieldOfViewRad; }

		void SetAmbientColor(const Color & color)
		{
			mAmbientColor = color;
			AmbientColor = XMVectorSet(mAmbientColor.R, mAmbientColor.G, mAmbientColor.B, mAmbientColor.A);
		}
		const Color & GetAmbientColor() const { return mAmbientColor; }

		Material * GetDefaultMaterial() const { return mDefaultMaterial; }

		const Camera & GetCamera() const { return mCamera; }
		Camera & GetEditableCamera() { return mCamera; }

		XMVECTOR AmbientColor;


		static const uint SPHERES_TAB_SIZE = 200;
		Sphere * Spheres;
		Material ** SphereMats;
		uint SpheresNum;
		uint getNextSphereIndex() { uint ret = SpheresNum++; assert(ret < SPHERES_TAB_SIZE); return ret; }

		static const uint PLANES_TAB_SIZE = 8;
		Plane * Planes;
		Material ** PlaneMats;
		uint PlanesNum;
		uint getNextPlaneIndex() { uint ret = PlanesNum++; assert(ret < PLANES_TAB_SIZE); return ret; }

		static const uint BOXES_TAB_SIZE = 8;
		Box * Boxes;
		Material ** BoxMats;
		uint BoxesNum;
		uint getNextBoxIndex() { uint ret = BoxesNum++; assert(ret < BOXES_TAB_SIZE); return ret; }

		static const uint BLOBS_TAB_SIZE = 2;
		Blob * Blobs;
		Material ** BlobMats;
		uint BlobsNum;
		uint getNextBlobIndex() { uint ret = BlobsNum++; assert(ret < BLOBS_TAB_SIZE); return ret; }

		static const uint ALGEBS_TAB_SIZE = 2;
		Algeb * Algebs;
		Material ** AlgebMats;
		uint AlgebsNum;
		uint getNextAlgebIndex() { uint ret = AlgebsNum++; assert(ret < ALGEBS_TAB_SIZE); return ret; }

	private:
		Camera mCamera;

		LightList mLights;

		std::vector<Material*> mMaterials;

		Material * mDefaultMaterial;

		float mFieldOfViewRad;
		Color mAmbientColor;
	};
}
